const acorn = require("acorn");
const analyze = require("./analyze");
const MagicString = require("magic-string");

class Module {
  constructor(options) {
    this.code = new MagicString(options.code);
    this.path = options.path;
    this.bundle = options.bundle;
    this.ast = acorn.parse(options.code, {
      locations: true, // 索引位置
      ranges: true,
      sourceType: "module",
      ecmaVersion: 7,
    });
    this.analyze();
  }
  analyze() {
    analyze(this.ast);
    this.imports = {};
    this.exports = {};
    this.definitions = {};
    this.ast.body.forEach((statement) => {
      if (statement.type == "ImportDeclaration") {
        statement.specifiers.forEach((spec) => {
          let localName = spec.local.name;
          let source = statement.source.value;
          let name = spec?.imported?.name || "";
          this.imports[localName] = {
            localName,
            name,
            source,
          };
        });
      }

      if (statement.type == "ExportNamedDeclaration") {
        /* a: {
  localName: 'a'
  node: {},
  expression: {}
} */
        statement.declaration.declarations.forEach((declaration) => {
          let name = declaration.id.name;
          this.exports[name] = {
            localName: name,
            node: statement,
            expression: statement.declaration,
          };
        });
      }
      if (statement.type == 'VariableDeclaration') {
        statement.declarations.forEach(declaration => {
          this.definitions[declaration.id.name] = statement
        })
      }
    });
  }

  expandAllStatements() {
    const allStatements = [];
    this.ast.body.forEach((statement) => {
      if (statement.type == "ExpressionStatement") {
        console.log(statement);
        const statements = this.expandStatement(statement);
        allStatements.push(...statements);
      }
    });
    return allStatements;
  }

  expandStatement(statement) {
    statement._included = true
    let statements = [];
    const keys = Object.keys(statement._dependsOn);
    keys.forEach((key) => {
      statements.push(...this.define(key));
    });
    statements.push(statement);
    return statements;
  }

  define(name) {
    let statement = this.definitions[name];
    if (name == 'console' || name == 'log') {
      return []
    } else if (statement._included) {
      return []
    } else {
      return this.expandStatement(statement)
    }

  }
}

module.exports = Module;
